import mapboxgl from "mapbox-gl";

type MapEventHandler = (bounds: mapboxgl.LngLatBounds, zoom: number) => void;

interface LabelHandlers {
  onDrag?: MapEventHandler;
  onZoom?: MapEventHandler;
}

interface LabelResources {
  sourceId: string;
  layerId: string;
  dragHandler?: () => void;
  zoomHandler?: () => void;
}

/**
 * 添加仅标签图层并设置事件监听
 * @param map Mapbox 地图实例
 * @param geojson GeoJSON 点数据
 * @param handlers 事件回调函数
 * @param layerId 图层ID (默认'label-layer')
 * @param sourceId 数据源ID (默认'label-source')
 * @param options 标签样式配置选项
 * @returns 返回资源对象，用于后续释放
 */
export function addLabelsOnly(
  map: mapboxgl.Map,
  geojson: GeoJSON.FeatureCollection<GeoJSON.Point>,
  handlers: LabelHandlers = {},
  layerId: string = "label-layer",
  sourceId: string = "label-source",
  options: {
    labelColor?: string;
    labelSize?: number;
    labelHaloColor?: string;
    labelHaloWidth?: number;
    labelOffset?: [number, number];
    labelAnchor?: "center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
  } = {}
): LabelResources {
  // 设置默认值
  const {
    labelColor = "#FFFFFF",
    labelSize = 12,
    labelHaloColor = "#000000",
    labelHaloWidth = 1,
    labelOffset = [0, 0],
    labelAnchor = "center"
  } = options;

  // 检查是否已存在相同ID的源和图层，如果存在则先移除
  if (map.getLayer(layerId)) {
    map.removeLayer(layerId);
  }
  if (map.getSource(sourceId)) {
    map.removeSource(sourceId);
  }

  // 添加数据源
  map.addSource(sourceId, {
    type: "geojson",
    data: geojson
  });

  // 添加仅标签图层
  map.addLayer({
    id: layerId,
    type: "symbol",
    source: sourceId,
    layout: {
      "text-field": ["get", "value"], // 显示 properties.value
      "text-size": labelSize,
      "text-offset": labelOffset,
      "text-anchor": labelAnchor,
      "text-variable-anchor": [labelAnchor],
      "text-radial-offset": 0,
      "text-justify": "auto",
      "text-font": ["MicrosoftYaHei"] // 设置字体
    },
    paint: {
      "text-color": labelColor,
      "text-halo-color": labelHaloColor,
      "text-halo-width": labelHaloWidth
    }
  });

  // 事件处理函数
  const handleMoveEnd = () => {
    if (handlers.onDrag) {
      handlers.onDrag(map.getBounds(), map.getZoom());
    }
  };

  const handleZoomEnd = () => {
    if (handlers.onZoom) {
      handlers.onZoom(map.getBounds(), map.getZoom());
    }
  };

  // 添加事件监听
  map.on("moveend", handleMoveEnd);
  map.on("zoomend", handleZoomEnd);

  // 返回资源对象，用于后续释放
  return {
    sourceId,
    layerId,
    dragHandler: handleMoveEnd,
    zoomHandler: handleZoomEnd
  };
}

/**
 * 更新标签数据
 * @param map Mapbox 地图实例
 * @param geojson 新的GeoJSON数据
 * @param sourceId 数据源ID (默认'label-source')
 */
export function updateLabels(
  map: mapboxgl.Map,
  geojson: GeoJSON.FeatureCollection<GeoJSON.Point>,
  sourceId: string = "label-source"
): void {
  const source = map.getSource(sourceId) as mapboxgl.GeoJSONSource;
  if (source) {
    source.setData(geojson);
  }
}

/**
 * 释放标签资源和事件监听
 * @param map Mapbox 地图实例
 * @param resources 由addLabelsOnly返回的资源对象
 */
export function releaseLabels(map: mapboxgl.Map, resources: LabelResources): void {
  const { sourceId, layerId, dragHandler, zoomHandler } = resources;

  // 移除事件监听
  if (dragHandler) {
    map.off("moveend", dragHandler);
  }
  if (zoomHandler) {
    map.off("zoomend", zoomHandler);
  }

  // 移除图层和源
  if (map.getLayer(layerId)) {
    map.removeLayer(layerId);
  }
  if (map.getSource(sourceId)) {
    map.removeSource(sourceId);
  }
}
